namespace Sidvall
{
    public class SystemContext
    {
        #region Public Members

        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used as a global cache.
        /// </summary>
        public Sidvall.Caching.CacheManager CacheManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to access application settings.
        /// </summary>
        public Sidvall.Configuration.SettingsManager SettingsManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Data.Filter, Sidvall.Data.FilterItem, Sidvall.Data.SortItem
        /// 
        /// Can be used to execute sql script.
        /// </summary>
        public Sidvall.Data.SqlManager SqlManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to start/end a transaction.
        /// </summary>
        public Sidvall.Data.ITransactionScopeFactory TransactionScopeFactory { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to use the camera
        /// </summary>
        public Sidvall.Devices.CameraManager CameraManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to use the GPS
        /// </summary>
        public Sidvall.Devices.GeolocatorFactoryManager GeolocatorFactoryManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Logging.LogManager
        /// 
        /// Can be used to get exception details.
        /// </summary>
        public Sidvall.ExceptionHandling.ExceptionManager SystemExceptionManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Dialogs.DialogManager, Sidvall.UI.Entities.MonitoredTaskItem
        /// 
        /// Can be used to get exception details.
        /// </summary>
        public Sidvall.ExceptionHandling.ExceptionManager UserExceptionManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Net.HttpClient, Sidvall.Globalization.CultureItemCollection, Sidvall.Globalization.CultureValueCollection, Sidvall.Resources.ResourceProviderBase
        /// 
        /// Can be used to access manage current culture.
        /// </summary>
        public Sidvall.Globalization.CultureManager CultureManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to manage zip files.
        /// </summary>
        public Sidvall.IO.Compression.IZipFileFactory ZipFileFactory { get; set; }
        /// <summary>
        /// Used by: Sidvall.Security.AuthenticationStrategyBase
        /// 
        /// Can be used by apps to store user settings.
        /// </summary>
        public Sidvall.IO.StorageManager UserStorageManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Office.ExcelManager, Sidvall.Reflection.CodeManager, Sidvall.Reflection.TypeCache
        /// 
        /// Can be used to access the filesytem used by the application. Internally it uses an Sidvall.IO.IStorage to
        /// communicate with the filesytem. Available implementations are:
        /// - Sidvall.IO.FileSystem:           System.IO
        /// - Sidvall.IO.Uwp.FileSystem:       System.IO.Uwp
        /// - Sidvall.IO.Net.NetFileSystem:    Sidvall.Net.HttpClient
        /// </summary>
        public Sidvall.IO.StorageManager SystemStorageManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Data.Entity.DataManager, Sidvall.Web.ControllerManager
        /// 
        /// Can be used to log.
        /// </summary>
        public Sidvall.Logging.LogManager LogManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Security.AuthenticationProvider, Sidvall.Net.Sms.SmsClient
        /// 
        /// Can be used to send/recieve messages via HTTP.
        /// </summary>
        public Sidvall.Net.IHttpClientFactory HttpClientFactory { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to send/recieve messages via SOAP.
        /// </summary>
        public Sidvall.Net.ISoapClientFactory SoapClientFactory { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Dialogs.DialogManager, Sidvall.UI.ViewModels.SecurityControlViewModel
        /// 
        /// Can be used to manage proxy settings
        /// </summary>
        public Sidvall.Net.ProxyStrategyManager ProxyStrategyManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to send emails.
        /// </summary>
        public Sidvall.Net.Mail.SmtpClientManager SmtpClientManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to send SMS.
        /// </summary>
        public Sidvall.Net.Sms.SmsClientManager SmsClientManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Views.FolderViewFinder, Sidvall.Data.SqlManager, Sidvall.Reflection.TypeCache
        /// 
        /// Can be used to access code constructs.
        /// </summary>
        public Sidvall.Reflection.CodeManager CodeManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Views.FolderViewFinder
        /// 
        /// Can be used to manage plugins (dll-files).
        /// </summary>
        public Sidvall.Reflection.TypeCache TypeCache { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Dialogs.MessageOptionCollection, Sidvall.UI.ViewModels.EntityListViewModelBase, Sidvall.UI.ViewModels.EntityViewModelBase
        /// 
        /// Can be used to access resource strings.
        /// </summary>
        public Sidvall.Resources.ResourceManager ResourceManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.ViewModels.SecurityControlViewModel
        /// 
        /// Can be used to authenticate users.
        /// </summary>
        public Sidvall.Security.AccountManager AccountManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Wpf.Dialogs.SecurityDialog, Sidvall.UI.Wpf.Dialogs.WebSecurityDialog
        /// 
        /// Can be used to authenticate users.
        /// </summary>
        public Sidvall.Security.AuthenticationManager AuthenticationManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Dialogs.DialogManager
        /// 
        /// Can be used to control authentication process.
        /// </summary>
        public Sidvall.Security.AuthenticationStrategyManager AuthenticationStrategyManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Web.ControllerManager
        /// 
        /// Can be used by web services to authorize users.
        /// </summary>
        public Sidvall.Security.AuthorizationManager AuthorizationManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Security.PrincipalManager
        /// 
        /// Can be used to manage principal claims.
        /// </summary>
        public Sidvall.Security.ClaimManager ClaimManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to store data for the current request. Internally it uses an Sidvall.Security.IPrincipalContextProvider to
        /// store data. Available implementations are:
        /// - Sidvall.Security.PrincipalContextProvider (System.Collections.Generic.Dictionary)
        /// - Sidvall.Web.Security.PrincipalContextProvider (System.Web.HttpContext.Current.Session)
        /// </summary>
        public Sidvall.Security.PrincipalContextManager PrincipalContextManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Security.AuthorizationManager, Sidvall.Security.UserManager
        /// 
        /// Can be used to manage System.Security.Principal.IPrincipal
        /// </summary>
        public Sidvall.Security.PrincipalManager PrincipalManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.Security.SecurityManager
        /// 
        /// Can be used to get/set user information.
        /// </summary>
        public Sidvall.Security.UserManager UserManager { get; set; }
        /// <summary>
        /// Used by: Sidvall.UI.Dialogs.DialogManager
        /// 
        /// Can be used to get/set user logon information.
        /// </summary>
        public Sidvall.Security.UserResponseStrategyManager UserResponseStrategyManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to launch external applications
        /// </summary>
        public Sidvall.SystemEnvironment.LauncherManager LauncherManager { get; set; }
        /// <summary>
        /// Used by: NOT USED
        /// 
        /// Can be used to Get package information
        /// </summary>
        public Sidvall.SystemEnvironment.PackageManager PackageManager { get; set; }

        #endregion
        #region Factory Members

        #region Current

        private static readonly object _Mutex = new object();
        private static volatile SystemContext _Current;
        public static SystemContext Current
        {
            get
            {
                if (_Current == null)
                {
                    lock (_Mutex)
                    {
                        if (_Current == null)
                        {
                            var item = new SystemContext()
                            {
                                AuthorizationManager = new Sidvall.Security.AuthorizationManager(new Sidvall.Security.PublicAuthorizationProvider()),
                                CodeManager = new Sidvall.Reflection.CodeManager(null),
                                CultureManager = new Sidvall.Globalization.CultureManager(new Sidvall.Globalization.CultureProvider()),
                                LogManager = new Sidvall.Logging.LogManager(new Sidvall.Logging.LogCollection()),
                                UserExceptionManager = new Sidvall.ExceptionHandling.ExceptionManager(new Sidvall.ExceptionHandling.UserExceptionProvider()),
                                SystemExceptionManager = new Sidvall.ExceptionHandling.ExceptionManager(new Sidvall.ExceptionHandling.SystemExceptionProvider()),
                                PrincipalContextManager = new Sidvall.Security.PrincipalContextManager(new Sidvall.Security.PrincipalContextProvider()),
                                ResourceManager = new Sidvall.Resources.ResourceManager(new Sidvall.Resources.ResourceProvider()),
                                SettingsManager = new Sidvall.Configuration.SettingsManager(null),
                                SqlManager = new Sidvall.Data.SqlManager(new Sidvall.Data.SqlProvider()),
                                TypeCache = new Sidvall.Reflection.TypeCache(),
                            };
                            _Current = item;
                        }
                    }
                }
                return _Current;
            }
            set
            {
                lock (_Mutex)
                {
                    _Current = value;
                }
            }
        }

        #endregion

        #endregion
        #region Constructors

        public SystemContext()
        {
        }

        #endregion
    }
}